package com.szlanyou.udpreceivermaster;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

import com.szlanyou.tcpservermaster.util.DoneLogger;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author 陈章
 * desc:
 * udp接收端核心类
 */
public class UdpReceiver {

    private static final String TAG = "UdpSocketServer";

    private AtomicBoolean isRun = new AtomicBoolean(false);
    private OnReceiverStatusListener onReceiverStatusListener;
    private int port;
    private final Handler childHandler;

    private final int MSG_TYPE_ENABLE_RECEIVER = 10;
    private final int MSG_TYPE_CLOSE_RECEIVER = 20;
    private final int MSG_TYPE_RELEASE = 30;

    /**
     * 该callback运行于子线程
     */
    private class ChildCallback implements Handler.Callback {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_TYPE_ENABLE_RECEIVER:
                    enableReceiverPrivate();
                    break;
                case MSG_TYPE_CLOSE_RECEIVER:
                    closeReceiverPrivate();
                    callbackReceiverClosed();
                    break;
                case MSG_TYPE_RELEASE:
                    closeReceiverPrivate();
                    childHandler.removeCallbacksAndMessages(null);
                    childHandler.getLooper().quit();
                    break;
            }
            return false;
        }
    }

    private void callbackReceiverClosed() {
        if (onReceiverStatusListener != null) {
            onReceiverStatusListener.onReceiverClosed();
        }
    }

    public UdpReceiver(int port) {
        this.port = port;
        HandlerThread handlerThread = new HandlerThread("udp_receiver " + this);
        handlerThread.start();
        //子线程Handler
        childHandler = new Handler(handlerThread.getLooper(), new ChildCallback());
    }

    public void enableReceiver() {
        if (!isRun.get()) {
            childHandler.obtainMessage(MSG_TYPE_ENABLE_RECEIVER).sendToTarget();
        }
    }

    public void closeReceiver() {
        if (isRun.get()) {
            childHandler.obtainMessage(MSG_TYPE_CLOSE_RECEIVER).sendToTarget();
        } else {
            DoneLogger.e(TAG, "the server not started,why do you close it ?");
        }
    }

    private void enableReceiverPrivate() {
        initReceiver();
    }

    private void closeReceiverPrivate() {
        isRun.set(false);
    }

    private void initReceiver() {
        try {
            //1. 创建一个udp socket
            DatagramSocket ds = new DatagramSocket(port);
            isRun.set(true);
            DoneLogger.d(TAG, "udp 接收端创建成功");
            if (onReceiverStatusListener != null) {
                onReceiverStatusListener.onReceiverStarted();
            }

            //接收发送端数据
            watchSender(ds);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void watchSender(DatagramSocket ds) throws IOException {
        //设置接收数据的最大值
        byte[] receive;
        //用于接收的数据
        DatagramPacket datagramPacket = null;
        while (isRun.get()) {
            receive = new byte[1024];
            //2. 创建一个用于接收数据。buf即数据和其长度
            datagramPacket = new DatagramPacket(receive, receive.length);
            //3. 接收byteBuff的数据，receive方法产生一个“阻塞”。
            ds.receive(datagramPacket);
            if(onReceiverStatusListener != null){
                int realLen = datagramPacket.getLength();
                byte[] realBuf = new byte[realLen];
                System.arraycopy(receive,0,realBuf,0,realLen);
                onReceiverStatusListener.onRead(realBuf);
            }
        }
    }

    public void listenReceiver(OnReceiverStatusListener onServerStatusListener) {
        this.onReceiverStatusListener = onServerStatusListener;
    }

    public void release() {
        childHandler.obtainMessage(MSG_TYPE_RELEASE).sendToTarget();
    }

    public interface OnReceiverStatusListener {
        /**
         * 接收端已经开启
         */
        void onReceiverStarted();

        /**
         * 接收端已经关闭
         */
        void onReceiverClosed();

        /**
         * 读取到的发送端的缓冲数据
         * @param buffer
         */
        void onRead(byte[] buffer);
    }

    public boolean isRun() {
        return isRun.get();
    }
}
